package com.sum.tea.xinlian.viewmodel

import com.sum.tea.contants.AppConfig
import com.uhf.api.cls.R2000_calibration
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import jxl.Workbook
import jxl.Sheet
import java.io.File

class SubRegopViewModel(application: Application) : AndroidViewModel(application) {

    val operationResult = MutableLiveData<String>()
    val regList = MutableLiveData<List<Map<String, String>>>()
    private val mAppConfig = AppConfig.getInstance()
    private val r2000pcmd = R2000_calibration()

    fun bytes_Hexstr(bArray: ByteArray, length: Int): String {
        val sb = StringBuilder(bArray.size)
        for (i in 0 until length) {
            val sTemp = Integer.toHexString(0xFF and bArray[i].toInt())
            if (sTemp.length < 2) sb.append("0")
            sb.append(sTemp.uppercase())
        }
        return sb.toString()
    }

    suspend fun readExcelFile(readfile: String) = withContext(Dispatchers.IO) {
        val list = mutableListOf<Map<String, String>>()
        list.add(mapOf("number" to "number", "address" to "address", "value" to "value"))
        try {
            val book: Workbook = Workbook.getWorkbook(File(readfile))
            val sheet: Sheet = book.getSheet(0)
            val rows = sheet.rows
            val cols = sheet.columns
            var regtype = 1

            // Determine regtype
            val firstCell = sheet.getCell(0, 0).contents.lowercase()
            regtype = when {
                firstCell.contains("bypass") -> 2
                firstCell.contains("oem") -> 0
                else -> 1
            }

            // Process each row
            for (i in 1 until rows) {
                var addr = 0.toShort()
                var valLong = 0
                for (j in 0 until cols) {
                    val content = sheet.getCell(j, i).contents
                    when (j) {
                        0 -> addr = content.toShort(16)
                        1 -> {
                            valLong = content.toShort(16).toInt() and 0xFFFFFFFF.toInt()
                        }
                    }
                }

                when (regtype) {
                    0 -> {
                        val oemData = r2000pcmd.OEM_DATA(addr, valLong)
                        sendCommand(R2000_calibration.R2000cmd.OEMwrite, oemData.ToByteData())
                    }
                    1 -> {
                        val macData = r2000pcmd.MAC_DATA(addr, valLong)
                        sendCommand(R2000_calibration.R2000cmd.writeMAC, macData.ToByteData())
                    }
                    2 -> {
                        sendRegopCommand(addr, valLong)
                    }
                }
            }

            book.close()
            withContext(Dispatchers.Main) {
                operationResult.value = "操作成功"
            }
        } catch (e: Exception) {
            withContext(Dispatchers.Main) {
                operationResult.value = e.message ?: "操作失败"
            }
        }
    }

    suspend fun readRegister(selectedType: Int, readAddress: String, readCount: String) = withContext(Dispatchers.IO) {
        try {
            if (readAddress.length > 4) throw Exception("地址溢出")
            val addr = readAddress.toShort(16)
            val count = readCount.toInt()

            val list = mutableListOf<Map<String, String>>()
            list.add(mapOf("number" to "number", "address" to "address", "value" to "value"))

            when (selectedType) {
                0 -> {
                    val oemData = r2000pcmd.OEM_DATA(addr)
                    for (i in 1 until count) {
                        oemData.AddTo((addr + i).toShort(), 0)
                    }
                    val response = sendCommand(R2000_calibration.R2000cmd.OEMread, oemData.ToByteData())
                    processOEMResponse(response, list)
                }
                1 -> {
                    val macData = r2000pcmd.MAC_DATA(addr)
                    for (i in 1 until count) {
                        macData.AddTo((addr + i).toShort(), 0)
                    }
                    val response = sendCommand(R2000_calibration.R2000cmd.readMAC, macData.ToByteData())
                    processMACResponse(response, list)
                }
                2 -> {
                    for (i in 0 until count) {
                        val currentAddr = (addr + i).toShort()
                        sendRegopCommand(currentAddr, 0)
                        // Assume value retrieval is handled inside sendRegopCommand
                        // You may need to adjust based on actual implementation
                    }
                }
            }

            withContext(Dispatchers.Main) {
                regList.value = list
                operationResult.value = "操作成功"
            }
        } catch (e: Exception) {
            withContext(Dispatchers.Main) {
                operationResult.value = "操作失败: ${e.message}"
            }
        }
    }

    suspend fun writeRegister(selectedType: Int, writeAddress: String, writeValue: String) = withContext(Dispatchers.IO) {
            try {
                if (writeAddress.length > 4) throw Exception("地址溢出")
                val addr = writeAddress.toShort(16)
                val valLong = writeValue.toLong(16).toInt() and 0xFFFFFFFF.toInt()

                when (selectedType) {
                    0 -> {
                        val oemData = r2000pcmd.OEM_DATA(addr, valLong)
                        sendCommand(R2000_calibration.R2000cmd.OEMwrite, oemData.ToByteData())
                    }
                    1 -> {
                        val macData = r2000pcmd.MAC_DATA(addr, valLong)
                        sendCommand(R2000_calibration.R2000cmd.writeMAC, macData.ToByteData())
                    }
                    2 -> {
                        sendRegopCommand(addr, valLong)
                    }
                }

                withContext(Dispatchers.Main) {
                    operationResult.value = "操作成功"
                }
            } catch (e: Exception) {
                withContext(Dispatchers.Main) {
                    operationResult.value = "操作失败: ${e.message}"
                }
            }
    }


    private suspend fun sendCommand(cmd: R2000_calibration.R2000cmd, data: ByteArray): ByteArray? {
        try {
            val sendData = r2000pcmd.GetSendCmd(cmd, data)
            mAppConfig.Mreader.DataTransportSend(sendData, sendData.size, 1000)

            val part1 = ByteArray(3)
            val re = mAppConfig.Mreader.DataTransportRecv(part1, part1.size, 1000)

            if (re == 0 && part1[2] != 0x00.toByte()) {
                val l = (part1[1].toInt() and 0xFF) + 4
                val part2 = ByteArray(l)
                val revdata = ByteArray(l + 3)
                System.arraycopy(part1, 0, revdata, 0, 3)
                val re2 = mAppConfig.Mreader.DataTransportRecv(part2, part2.size, 1000)
                if (re2 == 0) {
                    System.arraycopy(part2, 0, revdata, 3, part2.size)
                    return revdata
                }
            }
            throw Exception("收发指令失败")
        } catch (e: Exception) {
            throw e
        }
    }

    private suspend fun sendRegopCommand(addr: Short, value: Int) = withContext(Dispatchers.IO) {
        try {
            val data = byteArrayOf(
                0x07,
                ((addr.toInt() and 0xFF00) shr 8).toByte(),
                (addr.toInt() and 0x00FF).toByte(),
                ((value and 0xFF00) shr 8).toByte(),
                (value and 0x00FF).toByte()
            )
            val sendData = r2000pcmd.GetSendCmd(R2000_calibration.R2000cmd.Regop, data)
            mAppConfig.Mreader.DataTransportSend(sendData, sendData.size, 1000)

            val part1 = ByteArray(3)
            val re = mAppConfig.Mreader.DataTransportRecv(part1, part1.size, 1000)

            if (re == 0 && part1[2] != 0x00.toByte()) {
                val l = (part1[1].toInt() and 0xFF) + 4
                val part2 = ByteArray(l)
                val revdata = ByteArray(l + 3)
                System.arraycopy(part1, 0, revdata, 0, 3)
                val re2 = mAppConfig.Mreader.DataTransportRecv(part2, part2.size, 1000)
                if (re2 == 0) {
                    System.arraycopy(part2, 0, revdata, 3, part2.size)
                } else {
                    throw Exception("收发指令失败")
                }
            } else {
                throw Exception("收发指令失败")
            }
        } catch (e: Exception) {
            throw e
        }
    }

    private fun processOEMResponse(revdata: ByteArray?, list: MutableList<Map<String, String>>) {
        if (revdata == null) return
        val data = revdata.copyOfRange(17, revdata.size - 2)
        val r2000data = r2000pcmd.OEM_DATA(data)
        val adp = r2000data.GetAddr()
        adp.forEachIndexed { index, adpair ->
            val map = mapOf(
                "number" to "${index + 1}",
                "address" to String.format("%04x", adpair.addr),
                "value" to String.format("%04x", adpair.`val`)
            )
            list.add(map)
        }
    }

    private fun processMACResponse(revdata: ByteArray?, list: MutableList<Map<String, String>>) {
        if (revdata == null) return
        val data = revdata.copyOfRange(17, revdata.size - 2)
        val r2000data = r2000pcmd.MAC_DATA(data)
        val adp = r2000data.GetAddr()
        adp.forEachIndexed { index, adpair ->
            val map = mapOf(
                "number" to "${index + 1}",
                "address" to String.format("%04x", adpair.addr),
                "value" to String.format("%04x", adpair.`val`)
            )
            list.add(map)
        }
    }
}
